﻿using System;
using System.Collections.Generic;
using System.Linq.Expressions;

namespace Having.Site.Data.Lambda
{

    internal class QueryItem
    {
        public string Key { set; get; }
        public string Value { set; get; }
        public QueryItem() { }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public QueryItem(string key,string value) {
            this.Key = key;
            this.Value = value;
        }
    }

    /// <summary>
    /// 解析表达式
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class BaseSQLDataQuery<T> : IDataQuery<T> where T : class, new()
    {
        internal bool ispara = true;
        internal Dictionary<string, string> mlist = new Dictionary<string, string>();//select，update等主要操作（唯一）
        internal Dictionary<string, string> tlist = new Dictionary<string, string>();//select 到 from表 中间的自然部分（唯一的）
        internal Dictionary<string, string> plist = new Dictionary<string, string>();//select 到 from表 中间的函数部分（唯一的）
        internal List<QueryItem> wlist = new List<QueryItem>(); //条件，唯一的
        internal Dictionary<string, string> Glist = new Dictionary<string, string>(); // group by 排序唯一的
        internal Dictionary<string, string> Locklist = new Dictionary<string, string>(); //锁表操作
        internal List<QueryItem> Joinlist = new List<QueryItem>(); //链表操作
        internal List<QueryItem> Havinglist = new List<QueryItem>(); //Having子句
        internal List<string> Olist = new List<string>();
        internal LambdaRouter lr = null;

        internal Dictionary<string, dynamic> Dic = new Dictionary<string, dynamic>();

        /// <summary>
        /// 是否允许有参数值
        /// </summary>
        /// <param name="_ispara"></param>
        public BaseSQLDataQuery(bool _ispara=true)
        {
            this.ispara = _ispara;
            lr = new Lambda.LambdaRouter(ispara);
        }

        /// <summary>
        /// 返回
        /// </summary>
        public DataQueryResult Res
        {
            get
            {
                return new DataQueryResult(lr.Parameters, ToSql(), Dic);
            }
        }
        #region 方法
        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="exp"></param>
        /// <returns></returns>
        public IDataQuery<T> Delete(Expression<Func<T, bool>> exp=null)
        {
            string ex = null;
            if (exp != null)
            {
                ex = lr.ExpressionRouter(exp);
            }
            mlist.Add("Delete", ex);
            return this;
        }
        /// <summary>
        /// 插入
        /// </summary>
        /// <param name="exp"></param>
        /// <returns></returns>
        public IDataQuery<T> Insert(Expression<Func<T, bool>> exp)
        {
            var ex = lr.ExpressionRouter(exp);
            mlist.Add("Insert", ex);
            return this;
        }
        /// <summary>
        /// 查询
        /// </summary>
        /// <param name="exp"></param>
        /// <returns></returns>
        public IDataQuery<T> Select(Expression<Func<T, dynamic>> exp = null)
        {
            string ex = null;
            if (exp != null)
            {
                ex = lr.ExpressionRouter(exp);
                if (plist.ContainsKey("Filter"))
                {
                    plist["Filter"] +=","+ ex;
                }
                else
                {
                    plist.Add("Filter", ex);
                }
            }
            
            mlist.Add("Select",null);
            return this;
        }
        /// <summary>
        /// 更新
        /// </summary>
        /// <param name="exp"></param>
        /// <returns></returns>
        public IDataQuery<T> Update(Expression<Func<T, bool>> exp)
        {
            var ex = lr.ExpressionRouter(exp);
            mlist.Add("Update", ex);
            return this;
        }
        /// <summary>
        /// 更新
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public IDataQuery<T> Update(string str)
        {
            mlist.Add("Update", str);
            return this;
        }

        /// <summary>
        /// 返回树形结构
        /// </summary>
        /// <param name="exp">那个字段作为父字段</param>
        /// <returns></returns>
        public IDataQuery<T> Tree(Expression<Func<T, bool>> exp)
        {
            var ex = lr.ExpressionRouter(exp);
            mlist.Add("Tree", ex);
            return this;
        }

        #endregion



        #region join表(只针对select)
        internal IDataQuery<T> Basejion<T1>(Expression exp, string joinname)
        {
            var ex = lr.ExpressionRouter(exp, true);
            var exstr = ex.Replace(typeof(T1).Name, "_tj" + (Joinlist.Count + 1));
            Joinlist.Add(new QueryItem(joinname, typeof(T1).Name + " as _tj" + (Joinlist.Count + 1) + " on (" + exstr + ")"));
            return this;
        }
        /// <summary>
        /// 左链接
        /// </summary>
        /// <typeparam name="T1"></typeparam>
        /// <param name="exp"></param>
        /// <returns></returns>
        public IDataQuery<T> LeftJoin<T1>(Expression<Func<T1, bool>> exp) where T1 : class, new()
        {
            return Basejion<T1>(exp, "Left Join");
        }
        /// <summary>
        /// 左链接
        /// </summary>
        /// <typeparam name="T1"></typeparam>
        /// <param name="exp"></param>
        /// <returns></returns>
        public IDataQuery<T> LeftJoin<T1>(Expression<Func<T, T1, bool>> exp) where T1 : class, new()
        {
            return Basejion<T1>(exp, "Left Join");
        }

        /// <summary>
        /// 右链接
        /// </summary>
        /// <typeparam name="T1"></typeparam>
        /// <param name="exp"></param>
        /// <returns></returns>
        public IDataQuery<T> RightJoin<T1>(Expression<Func<T1, bool>> exp = null) where T1 : class, new()
        {
            return Basejion<T1>(exp, "Right Join");
            
        }
        /// <summary>
        /// 右链接
        /// </summary>
        /// <typeparam name="T1"></typeparam>
        /// <param name="exp"></param>
        /// <returns></returns>
        public IDataQuery<T> RightJoin<T1>(Expression<Func<T, T1, bool>> exp = null) where T1 : class, new()
        {
            return Basejion<T1>(exp, "Right Join");
        }
        /// <summary>
        /// InnerJoin
        /// </summary>
        /// <typeparam name="T1"></typeparam>
        /// <param name="exp"></param>
        /// <returns></returns>
        public IDataQuery<T> InnerJoin<T1>(Expression<Func<T1, bool>> exp = null) where T1 : class, new()
        {
            return Basejion<T1>(exp, "Inner Join");
        }

        /// <summary>
        /// InnerJoin
        /// </summary>
        /// <typeparam name="T1"></typeparam>
        /// <param name="exp"></param>
        /// <returns></returns>
        public IDataQuery<T> InnerJoin<T1>(Expression<Func<T, T1, bool>> exp = null) where T1 : class, new()
        {
            return Basejion<T1>(exp, "Inner Join");
        }

        #endregion

        #region select path from 表 中的path部分

        /// <summary>
        /// Avg（函数）
        /// </summary>
        /// <param name="exp"></param>
        /// <returns></returns>
        public IDataQuery<T> Avg(Expression<Func<T, dynamic>> exp)
        {
            var ex = lr.ExpressionRouter(exp);
            plist.Add("Avg", ex);
            return this;
        }
        /// <summary>
        /// Count（函数）
        /// </summary>
        /// <param name="exp"></param>
        /// <returns></returns>
        public IDataQuery<T> Count(Expression<Func<T, dynamic>> exp=null)
        {
            if (exp == null)
            {
                plist.Add("Count", "*");
            }
            else
            {
                var ex = lr.ExpressionRouter(exp);
                plist.Add("Count", ex);
            }
            return this;
        }

        

        /// <summary>
        /// Max（函数）
        /// </summary>
        /// <param name="exp"></param>
        /// <returns></returns>
        public IDataQuery<T> Max(Expression<Func<T, object>> exp)
        {
            var ex = lr.ExpressionRouter(exp);
            plist.Add("Max", ex);
            return this;
        }
        /// <summary>
        /// Min（函数）
        /// </summary>
        /// <param name="exp"></param>
        /// <returns></returns>
        public IDataQuery<T> Min(Expression<Func<T, dynamic>> exp)
        {
            var ex = lr.ExpressionRouter(exp);
            plist.Add("Min", ex);
            return this;
        }

        /// <summary>
        /// 获取列不重复的数据（自然）
        /// </summary>
        /// <param name="exp"></param>
        /// <returns></returns>
        public IDataQuery<T> Distinct(Expression<Func<T, dynamic>> exp)
        {
            var ex = lr.ExpressionRouter(exp);
            plist.Add("Distinct", ex);
            return this;
        }

        /// <summary>
        /// Filter
        /// </summary>
        /// <param name="filtername"></param>
        /// <returns></returns>
        public IDataQuery<T> Filter(string filtername) {
            if (plist.ContainsKey("Filter"))
            {
                plist["Filter"]+=","+filtername;
            }
            else
            {
                plist.Add("Filter", filtername);
            }
            return this;
        }
        /// <summary>
        /// Filter
        /// </summary>
        /// <param name="exp"></param>
        /// <returns></returns>
        public IDataQuery<T> Filter(Expression<Func<T, dynamic>> exp)
        {
            var ex = lr.ExpressionRouter(exp);
            var exs = ex.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
            var p = new List<string>();
            foreach (var item in exs)
            {
                p.Add(item.Trim().Replace("[","").Replace("]","") );
            }
            plist.Add("Filter", string.Join(",",p));
            return this;
        }
        /// <summary>
        /// sum（函数）
        /// </summary>
        /// <param name="exp"></param>
        /// <returns></returns>
        public IDataQuery<T> Sum(Expression<Func<T, dynamic>> exp)
        {
            var ex = lr.ExpressionRouter(exp);
            plist.Add("Sum", ex);
            return this;
        }
        /// <summary>
        /// top（自然）
        /// </summary>
        /// <param name="top"></param>
        /// <returns></returns>
        public IDataQuery<T> Take(int top)
        {
            plist.Add("Take", top.ToString());
            return this;
        }

        #endregion

        #region 锁
        /// <summary>
        /// 锁
        /// </summary>
        /// <param name="with"></param>
        /// <returns></returns>
        public IDataQuery<T> With(SQLWith with)
        {
            Locklist.Add("With", with.ToString());
            return this;
        }
        #endregion

        #region 条件
        public IDataQuery<T> Where(Expression<Func<T, bool>> exp=null)
        {
            if (exp != null)
            {
                
                var ex = lr.ExpressionRouter(exp);
                wlist.Add(new QueryItem("Where", ex));
            }
            return this;
        }

        public IDataQuery<T> Where(string str)
        {
            if (!string.IsNullOrWhiteSpace(str))
            {
                wlist.Add(new QueryItem("Where", str));
            }
            return this;
        }
        #endregion
        #region 排序
        /// <summary>
        /// 正排
        /// </summary>
        /// <param name="name">列名</param>
        /// <returns></returns>
        public IDataQuery<T> OrderBy(string name)
        {
            var ips = name.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
            foreach (var s in ips)
            {
                Olist.Add(s + " asc");
            }
            return this;
        }
        /// <summary>
        /// 正排序
        /// </summary>
        /// <param name="exp"></param>
        /// <returns></returns>
        public IDataQuery<T> OrderBy(Expression<Func<T, object>> exp)
        {
            var ex = lr.ExpressionRouter(exp);
            var exs = ex.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
            foreach (var item in exs)
            {
                Olist.Add("" + item.Trim() + " asc");
            }
            return this;
        }
        /// <summary>
        /// 倒排序
        /// </summary>
        /// <param name="name">列名</param>
        /// <returns></returns>
        public IDataQuery<T> OrderByDescending(string name)
        {
            var ips = name.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
            foreach (var s in ips)
            {
                Olist.Add(s + " desc");
            }
            return this;
        }
        /// <summary>
        /// 倒排
        /// </summary>
        /// <param name="exp"></param>
        /// <returns></returns>
        public IDataQuery<T> OrderByDescending(Expression<Func<T, object>> exp)
        {
            var ex = lr.ExpressionRouter(exp);
            var exs = ex.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
            foreach (var item in exs)
            {
                Olist.Add("" + item.Trim() + " desc");
            }
            return this;
        }

        /// <summary>
        /// 排序（正派）,在OrderBy/OrderByDescending后用，增加排序
        /// </summary>
        /// <param name="exp"></param>
        /// <returns></returns>
        public IDataQuery<T> ThenBy(Expression<Func<T, dynamic>> exp)
        {
            var ex = lr.ExpressionRouter(exp);
            var exs = ex.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
            foreach (var item in exs)
            {
                Olist.Add("" + item.Trim() + " asc");
            }
            return this;
        }
        /// <summary>
        /// 排序（倒排），在OrderBy/OrderByDescending后用，增加排序
        /// </summary>
        /// <param name="exp"></param>
        /// <returns></returns>
        public IDataQuery<T> ThenByDescending(Expression<Func<T, dynamic>> exp)
        {
            var ex = lr.ExpressionRouter(exp);
            var exs = ex.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
            foreach (var item in exs)
            {
                Olist.Add("" + item.Trim() + " desc");
            }
            return this;
        }
        /// <summary>
        /// 倒排序,在OrderBy/OrderByDescending后用，增加排序
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public IDataQuery<T> ThenByDescending(string name)
        {
            var ips = name.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
            foreach (var s in ips)
            {
                Olist.Add(s + " desc");
            }
            return this;
        }
        /// <summary>
        /// 正排序， 在OrderBy/OrderByDescending后用，增加排序
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public IDataQuery<T> ThenBy(string name)
        {
            var ips = name.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
            foreach (var s in ips)
            {
                Olist.Add(s + " asc");
            }
            return this;
        }

        /// <summary>
        /// 随机排序（性能不好，请谨慎使用）
        /// </summary>
        /// <returns></returns>
        public IDataQuery<T> OrderByRandom()
        {
            return this;
        }

        #endregion

        #region 分组
        public IDataQuery<T> GroupBy(Expression<Func<T, dynamic>> exp)
        {
            var ex = lr.ExpressionRouter(exp);
            Glist.Add("GroupBy", ex);
            return this;
        }
        #endregion
        # region 分页
        public IDataQuery<T> PageList(int page, int rows)
        {
            mlist.Add("PageList", "PageList");
            Dic["page"] = page;
            Dic["rows"] = rows;
            return this;
        }
        #endregion
        #region HAVING 子句
        internal IDataQuery<T> BaseHaving(Expression exp,string havingname)
        {
            var ex = lr.ExpressionRouter(exp);
            var exstr = ex.Replace("(", "").Replace(")", "").Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
            exstr[0] = havingname+"(" + exstr[0] + ")";
            Havinglist.Add(new QueryItem("having", string.Join("", exstr)));
            return this;
        }

        public IDataQuery<T> HavingCount(Expression<Func<T, bool>> exp) {
            return BaseHaving(exp, "Count");
        }
        //IDataQuery<T> HavingCount<T1>(Expression<Func<T1, bool>> exp) where T1:class,new();
        public IDataQuery<T> HavingSum(Expression<Func<T, bool>> exp)
        {
            return BaseHaving(exp, "Sum");
        }
        public IDataQuery<T> HavingAvg(Expression<Func<T, bool>> exp)
        {
            return BaseHaving(exp, "Avg");
        }

        #endregion
        /// <summary>
        /// 返回生成的Sql
        /// </summary>
        /// <returns></returns>
        public string ToSql()
        {
            string sql = "";
            return sql;
        }


    }
}
